#ifndef __UTILS_H__
#define __UTILS_H__

#define EPS 1e-10
#define INF 1e10

//! Compares two double values with some tolerance
/*! This method tests which value is greater
 *  If a is greater => return 1; if b is greater => return -1; otherwise, return 0
 *		@param x The first value to be compared
 *		@param y The second value to be compared
 *		@param tol The tolerance that is considered to be ZERO
 */
int CMP(double x, double y=0.0, double tol=EPS);

// ---------- Geometry algorithms -----------
#include "vec.h"
//* ----- Type Definition -----
typedef vec3 Point3D;

#include<utility>
#include <cstdio>
#include <algorithm>
using std::pair;
using std::make_pair;
using std::min;
typedef pair<Point3D,Point3D> Segment3D;

//! Calculates the distance between two points in a 3D world
/*!
 *	@param p the first point that will be considered
 *	@param q the second point that will be considered
 *	@return the distance between the two given points
 */
double squareDistance(Point3D p, Point3D q);

//! Calculates the distance between a segment and a point in a 3D world
/*!
 *	@param p the point that will be considered
 *	@param s the segment that will be considered
 *	@return the distance between the point and the segment
 */
double squareDistance(Point3D p, Segment3D s);

//! Tests if the two segments intersect with robustness in a 3D world
/*! 
 *	@param l1 the first segment that will be considered
 *	@param l2 the second segment that will be considered
 *	@return whether the two segments intersects or not
 */
bool segmentsIntersects(Segment3D l1, Segment3D l2);

//! Tests if the given point intersect the given triangle in a 3D world
/*!
 *	@param p0 the point that will be considered
 *	@param p1 the first vertex of the triangle
 *	@param p2 the second vertex of the triangle
 *	@param p3 the third vertex of the triangle
 *	@return whether or not the point in in the triangle
 */
bool pointInTriangle(Point3D p0, Point3D p1, Point3D p2, Point3D p3);

//! Tests if the given segment intersect the given triangle in a 3D world
/*!
 *	@param p0 the first vertex of the triangle
 *	@param p1 the second vertex of the triangle
 *	@param p2 the third vertex of the triangle
 *	@param seg the segment
 *	@return whether or not the segment intersects the tirangle
 */
bool segtriIntersects(Point3D p0, Point3D p1, Point3D p2, Segment3D seg);

//! Tests if the given point intersect the given rectangle in a 3D world
/*!
 *	@param p0 the point that will be considered
 *	@param p1 the first vertex of the rectangle
 *	@param p2 the second vertex of the rectangle
 *	@param p3 the third vertex of the rectangle
 *	@param p4 the fourth vertexx of the rectangle
 *	@return whether or not the point is in th rectangle
 */
bool pointInRectangle(Point3D p0, Point3D p1, Point3D p2, Point3D p3, Point3D p4);

//!	Tests if the given triangles intersects each other in a 3D world
/*!
 *	@param p1 the first vertex of the first triangle
 *	@param p2 the second vertex of the first triangle
 *	@param p3 the third vertex of the first triangle
 *	@param q1 the first vertex of the second triangle
 *	@param q2 the second vertex of the second triangle
 *	@param q3 the third vertex of the second triangle
 *	@return whether or not the triangles intersects each other
 */
bool triangleIntersects(Point3D p1, Point3D p2, Point3D p3, Point3D q1, Point3D q2, Point3D q3);

//! Tests if the given rectangles intersects each other in a 3D world
/*!
 *	@param p1 the first vertex of the first rectangle
 *	@param p2 the second vertex of the first rectangle
 *	@param p3 the third vertex of the first rectangle
 *	@param p4 the fourth vertex of the first rectangle
 *	@param q1 the first vertex of the second rectangle
 *	@param q2 the second vertex of the second rectangle
 *	@param q3 the third vertex of the second rectangle
 *	@param q4 the fourth vertex of the second rectangle
 *	@return whether or not the rectangles intersects each other
 */
bool rectangleIntersects(Point3D p1, Point3D p2, Point3D p3, Point3D p4, Point3D q1, Point3D q2, Point3D q3, Point3D q4);

//! Tests if the triangle and the rectangle intersects each other in a 3D world
/*!
 *	@param p1 the first vertex of the triangle
 *	@param p2 the second vertex of the triangle
 *	@param p3 the third vertex of the triangle
 *	@param q1 the first vertex of the rectangle
 *	@param q2 the second vertex of the rectangle
 *	@param q3 the third vertex of the rectangle
 *	@param q4 the fourth vertex of the rectangle
 *	@return whether or not the triangle and the rectangle intersects
 */
bool triangleRectangleIntersects(Point3D p1, Point3D p2, Point3D p3, Point3D q1, Point3D q2, Point3D q3, Point3D q4);
#endif
